
from sqlalchemy import and_, desc, exists, or_, text
from app.core.exception import ApiException
from app.entity.project import Project
from app.entity.projectGroup import ProjectGroup
from app.entity.projectUser import ProjectUser
from app.entity.user import User

from app.service.projectMessage import ProjectMessageService
from app.service.projectUser import ProjectUserService
from app.service.user import UserService
from app.utils.CommonUtils import tupleListToDict
from app.utils.RequestUtils import RequestUtils


class ProjectService:
    
    def transferProject(pid,userid):
        currentUserId=RequestUtils().getCurrentUserId()
        project=ProjectService.existsProject(pid)
        if not ProjectUserService.inProject(pid,userid): 
            raise ApiException("只能转让给项目成员")
        if currentUserId!=project.createBy:
            raise ApiException("非项目创建者，不可转入项目！")
        project.createBy=userid
        project.save()

    def quitProject(pid,userid):
        project=ProjectService.existsProject(pid)
        if not ProjectUserService.inProject(pid,userid): 
            raise ApiException("您已不是该项目的成员")
        if project.createBy==userid:
            raise ApiException("创建者无法退出,请先转让项目！")
        ProjectUser().query().where(and_(ProjectUser.projectId==pid,ProjectUser.userId==userid)).delete()

    def getBillData(projectId):
        connection= Project().getEngine().raw_connection()
        cursor_obj=connection.cursor()
        cursor_obj.callproc("prod_get_project_bill",[projectId])
        result1= tupleListToDict(cursor_obj.fetchall(),'pid,project_name,created_at,total_price,total_people,max_pay_people,max_pay_people_price,avg_price,max_pay_detail_price,max_pay_detail') 
        cursor_obj.nextset()
        result2=tupleListToDict(cursor_obj.fetchall(),'title,price,payer_desc')
        cursor_obj.nextset()
        result3=tupleListToDict(cursor_obj.fetchall(),'id,name,pay_price,num,yf_price,sjyf_price')
        cursor_obj.close()
        return {
            "project_name":result1[0]['project_name'],
            "create_date":result1[0]['created_at'],
            "total_price":result1[0]['total_price'],
            "total_people":result1[0]['total_people'],
            "max_detail":{
                "price":result1[0]['max_pay_detail_price'],
                "title":result1[0]['max_pay_detail']
            },
            "max_payer":{
                "payer_desc":result1[0]['max_pay_people'],
                "price":result1[0]['max_pay_people_price']
            },
            "detail_list":result2,
            "group_list":result3,
            "avg_price":result1[0]['avg_price']
        }

    def deleteProject(projectId):
        project=ProjectService.existsProject(projectId)
        currentUserId=RequestUtils().getCurrentUserId()
        currentUser=UserService.isValidUser(userid=currentUserId)
        allowDel=False
        if currentUser.isSuperAdmin=="Y":
            allowDel=True
        elif currentUser.id==project.createBy:
            allowDel=True
        if not allowDel:
            raise ApiException("您没有权限删除项目")
        project.status="X"
        project.deletedBy=currentUserId
        project.delete()
        projectUsers=ProjectUserService.getProjectUsers()
        for pu in projectUsers:
            if pu.userId==currentUserId:continue
            ProjectMessageService.sendSystemMessage(currentUserId,pu.userId,f"项目{project.name}已被解散","您所在的项目已被管理员解散！")

    def getProjectById(projectId)->Project:
        return Project().query().filter(Project.id==projectId).one()

    def inviteUser(projectId,inviter,invitee):
        project=ProjectService.existsProject(projectId)
        UserService.isValidUser(userid=invitee)
        inviterUser=UserService.isValidUser(userid=inviter)
        if inviter==invitee:
            raise ApiException("邀请者与被邀请者相同")
        if ProjectUserService.inProject(projectId,invitee):
            raise ApiException("用户已加入项目")
        if ProjectMessageService.hadInvitedMessage(projectId,invitee):
            raise ApiException("邀请已发送")
        title="你有新的项目邀请"
        message=f"{inviterUser.nickname}邀请你参加{project.name}项目！"
        toPage=f"{ProjectMessageService.toPage['invite']}?pid={projectId}"
        ProjectMessageService.sendSystemMessage(inviter,invitee,title,message,toPage)

    def updProject(postdata):
        project:Project=ProjectService.existsProject(postdata['id'])
        project.name=postdata['name']
        project.save()
        return project

    def existsProject(projectId):
        project:Project=Project().query().filter(Project.id==projectId).first()
        if project is None:
            raise ApiException("项目不存在")
        if project.deletedAt!=None:
            raise ApiException("项目已被删除")
        return project

    def getUserByProjectId(projectId)->list[User]:
        return User().query().join(ProjectUser,ProjectUser.userId==User.id).filter(ProjectUser.projectId==projectId).all()
    
    def addProject(data):
        project = Project()
        project.name = data['name']
        project.remask= data['remask']
        project.createBy=data['createdBy']
        # project.num=data['num']
        project.status="Y"
        project.save()
        ProjectUserService.joinProject(project.id,project.createBy,"Y")
        return project
    
    def addProjectGroup(data):
        pg=ProjectGroup()
        pg.name=data['name']
        pg.projectId=data['projectId']
        pg.createdBy=data['createdBy']
        pg.num=data['num']
        pg.save()
        return pg

    def getMyProjectList(userId)->list[Project]:
        exi=exists(text('1')).where(ProjectUser.projectId==Project.id).where(ProjectUser.userId==userId)
        projects=Project().query().where(Project.status=='Y').where(exi).order_by(desc(Project.createdAt)).all()
        return projects
    
    def getMyProjectData(projectId,userId):
        project:Project=Project().query().filter(Project.id==projectId).first()
        if project is None:
            return None
        count=ProjectUser().query().filter(and_(ProjectUser.projectId==project.id,ProjectUser.userId==userId)).count()
        if count==0:
            return None
        json=project.toJson()
        pu:ProjectUser=ProjectUser().query().where(and_(ProjectUser.projectId==project.id,ProjectUser.userId==userId)).first()
        puJson=pu.toJson()
        puJson["defalutGroupId_desc"]=pu.getDefalutGroupIdDescAttr()
        puJson['isAdmin']="Y" if userId==project.createBy else "N"
        json['projectUser']=puJson
        return json
    
    def updProjectGroup(groupId,postData):
        pg:ProjectGroup=ProjectService.existsProjectGroup(groupId)
        pg.name=postData['name']
        pg.num=postData['num']
        ProjectService.joinProjectGroupUsers(pg.projectId,groupId,postData['userList'])
        pg.save()
        return pg

    def existsProjectGroup(groupId):
        pg:ProjectGroup=ProjectGroup().query().where(ProjectGroup.id==groupId).first()
        if pg is None:
            raise ApiException("项目分组不存在")
        return pg

    def joinProjectGroup(groupId,userId):
        pg:ProjectGroup=ProjectService.existsProjectGroup(groupId)
        projectUser:ProjectUser=ProjectUser().query().where(and_(ProjectUser.projectId==pg.projectId,ProjectUser.userId==userId)).one()
        if projectUser==None:
            raise ApiException("用户未加入项目")
        projectUser.defalutGroupId=groupId
        projectUser.save()
    
    def joinProjectGroupUsers(projectId,groupId,userIds:list=[]):
        if userIds is None:
            userIds=[]
        ProjectUser().query().where(ProjectUser.defalutGroupId==groupId).update({ProjectUser.defalutGroupId:None})
        if len(userIds)>0:
            ProjectUser().query().where(and_(ProjectUser.projectId==projectId , ProjectUser.userId.in_(userIds)))\
                .update({ProjectUser.defalutGroupId:groupId})

    def getProjectGroupList(projectId)->list[ProjectGroup]:
        return ProjectGroup().query().filter(ProjectGroup.projectId==projectId).order_by(desc(ProjectGroup.createdAt)).all()

    def delProjectGroup(groupId):
        from app.service.projectDetails import ProjectDetailsService
        pg:ProjectGroup=ProjectService.existsProjectGroup(groupId)
        if ProjectDetailsService.getGroupDetailCount(groupId)>0:
            raise ApiException("分组下存在数据，无法删除")
        user=UserService.isValidUser(userid=RequestUtils().getCurrentUserId())
        pu=ProjectUserService.getProjectUser(pg.projectId,user.id)
        if pu == None :
            raise ApiException("您不是该项目的成员，无权删除分组")
        if user.isSuperAdmin!="Y" and pu.isAdmin!="Y" and user.id!=pg.createdBy :
            raise ApiException("您没有权限删除分组")
        pg.delete()
        pg.commit()